package com.atguigu.gulimall.product.service.impl;

import com.atguigu.gulimall.product.service.CategoryBrandRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 方法说明：
     *
     * @MethodName 查询出所有的商品分类信息,按照子父节点的方式进行排序
     * @Description    
     * @Author chenCheng
     * @Date 2022/9/22 15:40  
     * @修改人及日期：
     * @修改说明：
     */
    @Override
    public List<CategoryEntity> listWithTree() {
        // 1.查询出所有的分类信息
        List<CategoryEntity> entities = baseMapper.selectList(null);
        // 2.组装成父子的树结构
        // 2.1 先找到所有的一级分类,然后给一级分类的children设置子节点
        List<CategoryEntity> level1Menus =
                entities.stream()
                // 这个filter来过滤出我们需要的一级分类
                .filter(categoryEntity -> categoryEntity.getParentCid() == 0)
                // 这个map来为我们设置一级分类的子节点
                .map( (menu) -> {
                    // 给一级节点设置二级节点
                    menu.setChildren(getChildren(menu,entities));
                    return menu;
                })
                // 按照sort字段来进行排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                // 将收集号的数据转换成一个集合
                .collect(Collectors.toList());
        return level1Menus;
    }

    /**
     * 方法说明：
     *
     * @MethodName 查询出当前分类的完整路径(就是从他父节点一直到当前节点的一个信息)
     * @Description
     * @Author chenCheng
     * @EMAIL <2277411582@qq.com>
     * @Date 2022/9/24 14:31
     * @修改人及日期：
     * @修改说明：
     */
    @Override
    public Long[] findCatelogPath(Long catelogId) {

        //新建一个ArrayList集合 接受Long
        List<Long> paths = new ArrayList<>();
        // 给当前这个分类找爸爸
        List<Long> parentPath = findParentPath(catelogId, paths);
        
        //调用逆序方法获得正确顺序[2,25,225]
        Collections.reverse(parentPath);
        
        return parentPath.toArray(new Long[parentPath.size()]);
    }

    /**
     * 方法说明：
     *
     * @MethodName 修改分类信息时,同步修改相关关联表中的信息
     * @Description    
     * @Author chenCheng
     * @EMAIL <2277411582@qq.com>
     * @Date 2022/9/24 16:33  
     * @修改人及日期：
     * @修改说明：
     */
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        // 更新三级分类的信息
        this.updateById(category);
        // 更新相关关联表中的信息
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

    /**
     * 方法说明：
     *
     * @MethodName 给当前catelogId这个分类找爸爸
     * @Description    
     * @Author chenCheng
     * @EMAIL <2277411582@qq.com>
     * @Date 2022/9/24 14:34
     * @修改人及日期：
     * @修改说明：
     */
    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        // 收集当前这个节点
        paths.add(catelogId);
        // 查询出这个节点的信息,取出这个节点的爸爸的节点
        CategoryEntity categoryEntity = this.getById(catelogId);
        // 当前这个节点的父id不等于0,继续递归调
        if(categoryEntity.getParentCid() != 0){
            findParentPath(categoryEntity.getParentCid(),paths);
        }
        // 递归调用结束,返回这个集合
        return paths;
    }


    /**
    * 方法说明：
    *
    * @MethodName 给root节点及其子节点设置字节点
    * @Description
    * @Author chenCheng
    * @EMAIL <2277411582@qq.com>
    * @Date 2022/9/22 16:05
    * @修改人及日期：
    * @修改说明：
    */
    private List<CategoryEntity> getChildren(CategoryEntity root,List<CategoryEntity> all){
        // 1.先从所有的节点中找到当前root节点的子节点
        List<CategoryEntity> Children = all.stream()
                // 这个filter来过滤出我们需要的一级分类的子节点
                .filter(categoryEntity -> categoryEntity.getParentCid() == root.getCatId())
                // 我们过滤出来的这个categoryEntity可能也有子节点,在map中我们给这个过滤出来的categoryEntity设置子节点
                .map(categoryEntity ->{
                    // 给一级节点的二级节点设置子节点
                    categoryEntity.setChildren(getChildren(categoryEntity,all));
                    return categoryEntity;
                })
                // 按照sort字段来进行排序
                .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                // 将收集的数据转换成集合
                .collect(Collectors.toList());
        return Children;
    }
















}